

import javax.vecmath.Vector3d;


import java.util.List;
import java.util.Vector;


/**
 * Ein Mehrkoerpersystem stellt ein System von Himmelskoerpern im Raum dar, vergleichbar mit unserem Sonnensystem.
 * Das System hat eine gewisse Ausdehnung die durch einen Vector dargestellt wird.
 * Der Koerper mit der groessten Masse befindet sich im Zentrum und bewirkt das sich die anderen Koerper in einer gewissen
 * Umlaufbahn um das Zentralgestirn befinden.
 * 
 * @author r4smus
 */
public class MultiBodySystem {
	private int[] spaceCircumference; //index 0: untere Grenze des Raums, index 1: obere Grenze des Raums (nur Exponenten)
	private List<Body> bodyList;
	private Body centralBody;
	private int delta_t;
	private Vector3d simulationDirection = new Vector3d(0,0,1);
	



/**
 * Initialisiert die Startgeschwindigkeit fuer alle Koerper ausser dem centralBody.
 */
	public void initStartVelocitySys() {
		for (Body currentBody : bodyList) {
			currentBody.initStartVelocity(calcTotalMass(), calcTotalMassPosition(currentBody), simulationDirection);
		}
	}
	/**
	 * Berechne die Gesamtmasse aller Koerper.
	 */
	private double calcTotalMass(){
		// Berechne totalMass
		double totalMass = centralBody.getMass();
		for (Body body : bodyList) {
			totalMass += body.getMass();
		}
		return totalMass;
						
	}
	/**
	 * Berechnet die totalMassPosition ohne Beruecksichtigung des Koerpers b
	 * @param b
	 */
	private Vector3d calcTotalMassPosition(Body b){
		Vector3d totalMassPosition = new Vector3d();
		Vector3d currentPosition;
		totalMassPosition.add(centralBody.getPosition());
		for (Body body : bodyList) {
			if(body.equals(b)) // wenn der aktuelles K. gleich b, rest �berspringen und n�chster schleifendurchlauf
				continue;
			currentPosition = (Vector3d)body.getPosition().clone(); //Position des aktuellen Koerpers holen
			currentPosition.scale(body.getMass()); // Pos mit der Masse des aktuellen K. multiplizieren
			totalMassPosition.add(currentPosition); // Pos auf totalMassPos aufaddieren
		}
		totalMassPosition.scale( 1 / (calcTotalMass() - b.getMass()) );
		return totalMassPosition;
	}
	

	/**
	 * Berechnung der resultierenden Beschleunigungen die auf alle Koerper wirken, nach der Berechnung
	 * wird das Attribut acceleration im jeweiligen Body auf den berechneten Wert gesetzt.
	 */
	public void calcAccelerationSys() {
		Vector3d acclerationSys;
		for (Body currentBody : bodyList) {					
			acclerationSys = new Vector3d();		//aGes = Summe aller auf den Koerper wirkenden Beschl.	
			 // beschl. zum zentralgestr. berechnen
			acclerationSys.add(currentBody.calcAcceleration(centralBody)); // berechnete beschl.  aGes hinzuaddieren
			for (Body element : bodyList) { // aktBezugsK = aktueller BezugsK�rper
				if(element.equals(currentBody)) //Beschl. zum selben Koerper muss nicht berechnet werden!
					continue;				
				acclerationSys.add(currentBody.calcAcceleration(element)); // berechnete beschl. aGes hinzuaddieren				
			}
			currentBody.setAcceleration(acclerationSys);			
		}	
	}

	
	public void calcOneStep(){
		Master m =new Master(bodyList, centralBody, delta_t, 1);
		m.startWorker();
	}
	public void initCentralBody(double massCentralBody) {
		centralBody = new Body(1, massCentralBody, new Vector3d(0, 0, 0));
		
	}
	public int[] getSpaceCircumference(){
		return spaceCircumference;
	}
	public void setBodyList(List<Body> bodyList){
		this.bodyList = bodyList;
	}
	

	public List<Body> getBodyList(){
		return bodyList;
	}
	public void setSpaceCircumference(int[] spaceCircumference){
		this.spaceCircumference = spaceCircumference;
	}
	public void setDelta_t(int delta_t){
		this.delta_t = delta_t;
	}

}